package main

import (
	"flag"
	"fmt"
	"net/http"
	"usercenter/internal/biz"
	"usercenter/internal/config"
	"usercenter/internal/handler"
	"usercenter/internal/svc"

	"github.com/hashicorp/consul/api"
	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/rest/httpx"
	"github.com/zeromicro/zero-contrib/zrpc/registry/consul"
)

var configFile = flag.String("f", "etc/usercenter-api.yaml", "the config file")

func main() {
	flag.Parse()

	// 设置全局错误处理器
	httpx.SetErrorHandler(func(err error) (int, interface{}) {
		// 判断是否为自定义错误
		if bizErr, ok := err.(*biz.BizError); ok {
			return http.StatusOK, map[string]interface{}{
				"code":    bizErr.Code, // 动态错误码
				"message": bizErr.Message,
			}
		}

		// 默认错误（未识别的错误类型）
		return http.StatusOK, map[string]interface{}{
			"code":    -1, // 默认错误码
			"message": err.Error(),
		}
	})

	// 1. 先加载本地基础配置（包含Consul连接信息）
	var baseConfig config.BaseConfig
	conf.MustLoad(*configFile, &baseConfig)

	// 2. 从Consul KV加载配置
	kvConfig, err := loadConfigFromConsulKV(
		baseConfig.Consul.Host,
		baseConfig.Consul.ConfigKey, // 假设你的配置中有一个ConfigKey字段
		baseConfig.Consul.Token,
	)
	if err != nil {
		panic(fmt.Errorf("failed to load config from consul kv: %v", err))
	}

	// 3. 合并配置
	var c config.Config
	if err := conf.LoadFromJsonBytes(kvConfig, &c); err != nil {
		panic(fmt.Errorf("failed to parse consul kv config: %v", err))
	}

	// 4. 用本地配置覆盖或补充Consul配置（如果需要）
	// 这里可以根据需要合并本地和远程配置
	// 例如: c.Host = baseConfig.Host

	// 5. 注册服务到Consul
	listenOn := fmt.Sprintf("%s:%d", c.Host, c.Port)
	err = consul.RegisterService(listenOn, consul.Conf{
		Host:  baseConfig.Consul.Host,
		Key:   baseConfig.Consul.Key,
		Token: baseConfig.Consul.Token,
		TTL:   baseConfig.Consul.TTL,
	})
	if err != nil {
		panic(err)
	}

	// 6. 启动服务
	server := rest.MustNewServer(c.RestConf)
	defer server.Stop()

	ctx := svc.NewServiceContext(c)
	handler.RegisterHandlers(server, ctx)

	fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
	fmt.Printf("JWT Config: %+v\n", c.JWT)
	fmt.Printf("DB Config: %+v\n", c.DB)
	fmt.Printf("Redis Config: %+v\n", c.Redis)
	fmt.Printf("Email Config: %+v\n", c.Email)
	fmt.Printf("MinIO Config: %+v\n", c.Minio)
	// 输出服务初始化状态
	fmt.Println("=== 服务初始化状态 ===")
	fmt.Printf("数据库: %v\n", ctx.DB != nil)
	fmt.Printf("Redis: %v\n", ctx.Redis != nil)
	fmt.Printf("验证码服务: %v\n", ctx.VerificationMgr != nil)
	fmt.Printf("用户模型: %v\n", ctx.UserModel != nil)
	fmt.Printf("Gorse: %v\n", ctx.GorseClient != nil)
	fmt.Println("====================")
	server.Start()
}

func loadConfigFromConsulKV(consulHost, consulKey, consulToken string) ([]byte, error) {
	// 创建Consul客户端配置
	config := api.DefaultConfig()
	config.Address = consulHost
	config.Token = consulToken

	// 创建客户端
	client, err := api.NewClient(config)
	if err != nil {
		return nil, fmt.Errorf("failed to create consul client: %v", err)
	}

	// 获取KV
	kv := client.KV()
	pair, _, err := kv.Get(consulKey, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get kv from consul: %v", err)
	}

	if pair == nil {
		return nil, fmt.Errorf("no such key in consul: %s", consulKey)
	}

	return pair.Value, nil
}

